package playerdef

import (
	"encoding/json"
	"fmt"
	"sync"
	"time"
	"wanyu/server/engine/globaldef/consts"
	"wanyu/server/engine/wpcfg"
	"wanyu/server/engine/wplog"
)

type AttrProb struct {
	Name  string
	Type  string
	Flags string
	Send  bool
	Save  bool
	Value interface{}
}

var (
	rwMutex        sync.RWMutex
	playerAttrProb map[string]*AttrProb
)

func LoadPlayerDefProb(configfile string, bIsRetNew bool) (interface{}, error) {
	rwMutex.Lock()
	defer rwMutex.Unlock()

	var retmap map[string]interface{}
	// 读取配置
	if _, err := wpcfg.SyncLoadFile(consts.ConfigPlayer, configfile); err != nil {
		return nil, err
	}

	playerdef, err := wpcfg.Map(consts.ConfigPlayer)

	if err != nil {
		return nil, err
	}
	if playerAttrProb == nil {
		playerAttrProb = make(map[string]*AttrProb)
	}
	if bIsRetNew {
		retmap = make(map[string]interface{})
	}
	for key, keyprob := range playerdef {
		_, ok := playerAttrProb[key]
		if ok {
			continue
		}
		probMap, ok := keyprob.(map[string]interface{})
		if !ok {
			wplog.Infof("playerdef config key = %s keyprob map error", key)
			return nil, fmt.Errorf("playerdef config key = %s keyprob map error", key)
		}
		attrinfo := new(AttrProb)
		attrinfo.Name = key
		attrinfo.Flags, ok = probMap["flags"].(string)
		if !ok {
			wplog.Infof("playerdef config key = %s flags error", key)
			return nil, fmt.Errorf("playerdef config key = %s flags error", key)
		}
		attrinfo.Send, ok = probMap["send"].(bool)
		if !ok {
			wplog.Infof("playerdef config key = %s send error", key)
			return nil, fmt.Errorf("playerdef config key = %s send error", key)
		}
		attrinfo.Save, ok = probMap["save"].(bool)
		if !ok {
			wplog.Infof("playerdef config key = %s save error", key)
			return nil, fmt.Errorf("playerdef config key = %s save error", key)
		}
		attrinfo.Type, ok = probMap["type"].(string)
		if !ok {
			wplog.Infof("playerdef config key = %s type error", key)
			return nil, fmt.Errorf("playerdef config key = %s type error", key)
		}
		switch attrinfo.Type {
		case "int32":
			number := probMap["default"].(json.Number)
			value, err := number.Int64()
			if err != nil {
				wplog.Infof("playerdef config key = %s default value error type not match", key)
				return nil, err
			}
			attrinfo.Value = int32(value)
			if bIsRetNew {
				retmap[key] = int32(value)
			}
		case "int64":
			number := probMap["default"].(json.Number)
			value, err := number.Int64()
			if err != nil {
				wplog.Infof("playerdef config key = %s default value error type not match", key)
				return nil, err
			}
			attrinfo.Value = value
			if bIsRetNew {
				retmap[key] = value
			}
		case "float32":
			number := probMap["default"].(json.Number)
			value, err := number.Float64()
			if err != nil {
				wplog.Infof("playerdef config key = %s default value error type not match", key)
				return nil, err
			}
			attrinfo.Value = float32(value)
			if bIsRetNew {
				retmap[key] = float32(value)
			}
		case "float64":
			number := probMap["default"].(json.Number)
			value, err := number.Float64()
			if err != nil {
				wplog.Infof("playerdef config key = %s default value error type not match", key)
				return nil, err
			}
			attrinfo.Value = value
			if bIsRetNew {
				retmap[key] = value
			}
		case "string":
			value := probMap["default"].(string)
			attrinfo.Value = value
			if bIsRetNew {
				retmap[key] = value
			}
		case "bool":
			value := probMap["default"].(bool)
			attrinfo.Value = value
			if bIsRetNew {
				retmap[key] = value
			}
		case "time":
			number := probMap["default"].(json.Number)
			value, err := number.Int64()
			if err != nil {
				wplog.Infof("playerdef config key = %s default value error type not match", key)
				return nil, err
			}
			theTime := time.Unix(value, 0)
			attrinfo.Value = theTime
			if bIsRetNew {
				retmap[key] = theTime
			}
		default:
			wplog.Infof("playerdef config key = %s no this type", key)
			return nil, fmt.Errorf("playerdef config key = %s no this type", key)
		}
		playerAttrProb[key] = attrinfo
	}

	if bIsRetNew && len(retmap) > 0 {
		return retmap, nil
	}

	return nil, nil
}

func IsInConfig(keyname string) bool {
	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if _, ok := playerAttrProb[keyname]; ok {
		return true
	}

	return false
}

func IsBase(keyname string) bool {
	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if prob, ok := playerAttrProb[keyname]; ok {
		return prob.Flags == "base"
	}
	return false
}

func IsTemp(keyname string) bool {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if prob, ok := playerAttrProb[keyname]; ok {
		return prob.Flags == "temp"
	}

	return false
}

func IsSend(keyname string) bool {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if prob, ok := playerAttrProb[keyname]; ok {
		return prob.Send
	}

	return false
}

func IsSave(keyname string) bool {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if attrinfo, ok := playerAttrProb[keyname]; ok {
		return attrinfo.Save
	}
	return false
}

func GetAttrFlags(keyname string) string {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if attrinfo, ok := playerAttrProb[keyname]; ok {
		return attrinfo.Flags
	}

	return ""
}

func GetAttrDefaultValue(keyname string) (interface{}, error) {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if attrinfo, ok := playerAttrProb[keyname]; ok {
		return attrinfo.Value, nil
	}

	return nil, fmt.Errorf("this key = %s default value not exist", keyname)
}

func GetAttrDefaultBaseData() map[string]interface{} {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	baseData := make(map[string]interface{})

	for key, keyprob := range playerAttrProb {
		if keyprob.Flags == "base" {
			baseData[key] = keyprob.Value
		}
	}
	return baseData
}

func GetAttrDefaultTempData() map[string]interface{} {

	rwMutex.RLock()
	defer rwMutex.RUnlock()

	tempData := make(map[string]interface{})

	for key, keyprob := range playerAttrProb {
		if keyprob.Flags == "temp" {
			tempData[key] = keyprob.Value
		}
	}
	return tempData
}

func GetAttrDefaultMapKeyValue() map[string]interface{} {
	rwMutex.RLock()
	defer rwMutex.RUnlock()

	defaultkeyvalue := make(map[string]interface{}, 64)
	for key, keyprob := range playerAttrProb {
		defaultkeyvalue[key] = keyprob.Value
	}

	return defaultkeyvalue
}

func GetAttrValue(keyname string, invalue interface{}) (interface{}, error) {
	rwMutex.RLock()
	defer rwMutex.RUnlock()

	if attrinfo, ok := playerAttrProb[keyname]; ok {
		switch attrinfo.Type {
		case "int32":
			return invalue.(int32), nil

		case "int64":
			return invalue.(int64), nil

		case "float32":
			return invalue.(float32), nil

		case "float64":
			return invalue.(float64), nil

		case "string":
			return invalue.(string), nil

		case "time":
			return time.Unix(invalue.(int64), 0), nil

		default:
			wplog.Infof("playerdef config key = %s no this type", keyname)
			return nil, fmt.Errorf("playerdef config key = %s no this type", keyname)
		}
	}

	return nil, fmt.Errorf("this key = %s not exist", keyname)
}
